﻿#region

using System;
using System.Configuration;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using log4net;

#endregion

namespace Jiubang.Wap.HttpModules{
    /// <summary>
    ///   添加该Module查询字符串中sid为空或不存在时，
    ///   将执行一次302跳转并使查询字符串带上sid=(临时sid)
    /// </summary>
    public sealed class TempSidModule : IHttpModule{
        private const string ManagedPageExtension = ".aspx";
        private const string Userforever = "3guser_forever";
        private const string Gguserforever = "gguser_forever";
        private const string Usersid = "UserSid";
        private static readonly int channelId;
        private static readonly ILog log = LogManager.GetLogger(typeof (TempSidModule));

        static TempSidModule(){
            int.TryParse(ConfigurationManager.AppSettings["Chid"], out channelId);
        }

        #region IHttpModule Members

        /// <summary>
        ///   绑定事件
        /// </summary>
        /// <param name = "context"></param>
        public void Init(HttpApplication context){
            context.BeginRequest += ContextBeginRequest;
        }

        /// <summary>
        ///   空操作
        /// </summary>
        public void Dispose(){
        }

        #endregion

        private static void ContextBeginRequest(object sender, EventArgs e){
            var context = ((HttpApplication) sender).Context;
            var path = context.Request.AppRelativeCurrentExecutionFilePath;
            path = path.Remove(0, 2);
            var extName = Path.GetExtension(path);
            if (extName.Length <= 0 ||
                string.Compare(extName, ManagedPageExtension, StringComparison.CurrentCultureIgnoreCase) != 0) return;
            if (context.Request.Form.Count > 0)
                return;

            var sid = context.Request.QueryString.Get("sid");
            var isEmpty = string.IsNullOrEmpty(sid);
            //如果是登录用户，直接返回
            if (!isEmpty && sid.Length >= 20) return;
            //如果是手机号用户，直接返回
            if (!isEmpty && sid.Length >= 18 && IsMobileSid(sid)) return;
            //cookie中是否有登录sid,如果有，则重写链接并返回
            var loginCookie = context.Request.Cookies[Userforever];
            if (loginCookie != null){
                var loginSid = loginCookie[Usersid];
                if (!string.IsNullOrEmpty(loginSid) &&
                    string.Compare(sid, loginSid, StringComparison.CurrentCultureIgnoreCase) != 0){
                    context.Response.Redirect(RewriteUrl(context, loginSid), true);
                    return;
                }
            }
            //cookie中是否有手机号sid，如果有，则重写链接并返回
            
            var mobileCookie = context.Request.Cookies[Gguserforever];
            if (mobileCookie != null){
                var mobileSid = mobileCookie[Usersid];
                if (!string.IsNullOrEmpty(mobileSid) &&
                    string.Compare(sid, mobileSid, StringComparison.CurrentCultureIgnoreCase) != 0){
                    context.Response.Redirect(RewriteUrl(context, mobileSid), true);
                    return;
                }
            }
            if (!isEmpty) return;
            sid = UserAuthorize.BuildTempSid(DateTime.Now, channelId);
            context.Response.Redirect(RewriteUrl(context, sid), true);
        }

        private static string RewriteUrl(HttpContext context, string sid){
            var url = context.Request.RawUrl;
            var sb = new StringBuilder(200);
            var index = url.IndexOf("?");
            sb.Append(index == -1 ? url + "?" : url.Substring(0, index + 1));
            var isChange = false;
            foreach (string s in context.Request.QueryString){
                if (!isChange && s == "sid"){
                    isChange = true;
                    sb.Append("sid=" + sid + "&");
                } else sb.Append(s + "=" + HttpUtility.UrlEncode(context.Request.QueryString[s]) + "&");
            }
            if (!isChange) sb.Append("sid=" + sid);
            return sb[sb.Length - 1] == '&' ? sb.Remove(sb.Length - 1, 1).ToString() : sb.ToString();
        }

        private static bool IsMobileSid(string sid){
            return GetPhoneNumber(sid)>0;
        }

        /// <summary>
        ///   从字符中解析出手机号码
        /// </summary>
        /// <param name = "num"></param>
        /// <returns></returns>
        public static long GetPhoneNumber(string num){
            if (string.IsNullOrEmpty(num)) return 0;
            if (num.Length < 18||num.Length>19) return 0;
            if (Regex.IsMatch(num, @"[^0-9]+")) return 0;
            var mymob = "";
            try{
                //解密的映射数组
                int[] unkey = {3, 1, 4, 9, 7, 2, 0, 5, 8, 6};
                num = num.Length == 18 ? num.Substring(3, num.Length - 5) : num.Substring(4, num.Length - 6);
                var valisum = num.Substring(num.Length - 2); //得到验证码
                num = num.Substring(0, num.Length - 2); //得到密码
                var secretnum = new int[num.Length];
                //反映射回原来的数值
                for (var i = 0; i < num.Length; i++){
                    secretnum[i] = int.Parse(num.Substring(i, 1));
                    secretnum[i] = unkey[secretnum[i]];
                }
                //将第一位与最后一位互换，第二位与最后第二位互换……换为原来的顺序 
                for (var i = 0; i < secretnum.Length/2; i++){
                    var temp = secretnum[i];
                    secretnum[i] = secretnum[secretnum.Length - 1 - i];
                    secretnum[secretnum.Length - 1 - i] = temp;
                }
                var sum = 0;
                num = "";
                //每一位按原来的逆运算减1得到初始值
                for (var i = 0; i < secretnum.Length; i++){
                    if (secretnum[i] >= 1)
                        secretnum[i] = secretnum[i] - 1;
                    else
                        secretnum[i] = (secretnum[i] + 10) - 1;
                    sum = sum + secretnum[i];
                    num = num + secretnum[i];
                }
                mymob = sum%100 == int.Parse(valisum) ? num : "";
            } catch (Exception e){
                log.Error(e);
            }

            long phone;
            long.TryParse(mymob, out phone);
            return phone;
        }
    }
}